<?php

!defined('DEBUG') AND exit('Access Denied.');
//ghxpost-{cmd}-{pid}-{Operator}.htm
/**
 * 请求格式说明
 * URL:ghxpost-{cmd}-{pid}-{Operator}.htm
 * {cmd}可以是:{flag},getinfo,striphtml,clear,flags,postflag,batch
 * {cmd}={flag}:单个标记,只能对一个pid进行操作
 *          _POST(reason) 为标记原因
 *           {pid} 为要操作的回帖ID,必须
 *          会对权限进行严格验证,在标记成功时,全清除同组的标记;会在$retarr['sucopt']['del']和$retarr['sucopt']['add']中记录
 *          生成的参数格式为:'{flag}'=>'{reason}'
 * {cmd}=flags:多个标记,可以是多个PID
 *           _POST(list) 为标记内容的列表,字符串格式:[分隔符]{pid}:{flag}:{reason}[分隔符]{pid2}:{flag2}:{reason2}
 *                      如果第一个字符是正常的字母,分隔符默认为|,如果二级中不存在{pid},则使用URL中的pid参数值
 *                      示例:|226:nay:反对庸俗主义|tobe:秉公任直,推荐
 *                      此参数为必须,格式可能为数组,或者{}包裹的JSON字符串
 *           {pid} 为要操作的回帖ID,必须
 *          会对权限进行严格验证,在标记成功时,会在$retarr['sucopt']['del']和$retarr['sucopt']['add']中记录
 *           生成的参数格式为:array('{flag}'=>'{reason}','{flag2}'=>'{reason2}'...)
 * {cmd}=clear:清除标记,必须要有论坛管理权限,可以对多个pid进行操作
 *           _POST(list) 为清除标记的列表,格式:[分隔符]{pid}:{flag1,flag2,flag3...}[分隔符]{pid2}:{flag1,flag2,flag3...}
 *                      如果第一个字符是正常的字母,分隔符默认为|
 *                      示例:|25:nay,tobe|28:work,much
 *          {pid} 为要操作的回帖ID,可选,如果_POST(list)中没有提供pid,则以此为pid,以_POST(list)为逗号分隔的标记列表
 *          会对权限进行严格验证,在标记成功时,会在$retarr['sucopt']['del']中记录
 *           生成的参数格式为:array({pid}=>array({flags}))
 * {cmd}=striphtml:清除指定回帖的HTML格式,要求调用者有论坛管理权限,可以对多个pid进行操作
 *            _POST(list) 为清除HTML格式的pid,第一个字符为分隔符,如果第一个字符是正常的字母,分隔符默认为,
 *            {pid} 为要操作的回帖ID,可选,在_POST(list)没有指定时,以此为操作pid
 *            _POST('preserve') 要保留的标签,示例:<a><img>
 *            处理成功后会在$retArr['sucopt']['message_fmt']=array({pid1}=>'{message_fmt}',{pid2}=>'{message_fmt}')中记录
 *           生成的参数格式为:array('list'=>array({pid数组},'preserve'=>'保留标签表')
 * {cmd}=getinfo:获取标记详情,可以对多个pid进行操作
 *            _POST(list) 为要获取标记详情postflag表的pid和标记列表,格式:[分隔符]{pid}:{flag1,flag2,flag3...}[分隔符]{pid2}:{flag1,flag2,flag3...}
 *            第一个字符为分隔符,如果第一个字符是正常的字母,分隔符默认为;
 *            {pid} 为要操作的postflag表的pid,可选,在_POST(list)没有指定时,以此为操作pid,此时_POST(list)为标记列表
 *            处理成功后会在$retArr['sucopt']['getinfo']=array({pid1}=>array({flag}=>'{info}',{flag2}=>'{info}'),{pid2}=>array({flag}=>'{info}'))中记录
 *            生成的参数格式为:array({pid}=>array({flags}))
 * {cmd}=batch:批量处理,包括以上所有操作
 *             _POST(list) 参数内容,必须,要用json_encode($paramArr)处理后的字符串
 *                          在批处理中,第一个缺失pid的某类操作,可以用{pid}代替
 *                          参数的格式,要符合以上各参数生成后的参数格式,否则不能正确处理!
 *
 *
 * 返回结果:array('message'=>提示消息,'code'=>代码值,'errorno'=>错误号,'pid'=>操作的pid,'sucopt'=>array({add},{del},{other},{message_fmt},{getinfo}))
 */
//-----------------------------------------------------------
/**
 * 允许执行的命令表:
 */
$valid_cmd = array('getinfo', 'striphtml', 'clear', 'flags','postflag','batch');
$valid_actives = array('getinfo', 'striphtml', 'clear', 'postflag');//有效的指令
/**
 * 根据指定pid与条件设置来获取相关的主题帖子列表
 * @param int $pid
 * @param string|array $rules 条件设置,字符串时多个以一般分隔符分隔,举例:fid;fid=2;keywords_-1,keywords=tea
 * $rules中的keywords_-1表示指定pid主题帖子的keywords中的倒数第一个关键词
 * @param bool $noCache 是否不从缓存结果中返回(如果有),默认为false
 * @return array array({pid}=>array(pid,tid,keywords)),keywords可能不存在
 */
function &PickupFirstPosts(int $pid,$rules,$noCache=false){
    static $retarr = array();
    $ret = array();
    if(!empty($rules) && $pid > 0){
        $md5 = strval($pid);
        if(is_array($rules)) $md5.= implode(',',$rules);
        else $md5.= $rules;
        $md5 = md5($md5);
        if(isset($retarr[$md5]) && !$noCache) //从缓存读取并返回:
            return $retarr[$md5];
        if(is_string($rules)){
            $rules = preg_split('/[\t\n,;\|]+|\s{2,}/u',$rules);
        }
        $MAX_ONCE_READ = 2048;
        $selectfs = array();
        foreach($rules as $rule){
            if('fid' == $rule){
                if(!isset($selectfs['fid'])) $selectfs['fid'] = array(0);
                elseif(!in_array(0,$selectfs['fid'])) $selectfs['fid'][] = 0;
            }
            elseif('keywords' == substr($rule,0,8)){
                if(!isset($selectfs['keywords'])) $selectfs['keywords'] = array();
                $lineno = 0;
                if(strlen($rule) > 9){
                    if('=' != $rule{8}) {
                        $lno = substr($rule, 9);
                        if (is_numeric($lno)) $lineno = (int)$lno;
                        if ($lineno > 0) $lineno--;
                    }
                    else{
                        $lineno = null;
                        $selectfs['keywords']['value'] = substr($rule, 9);
                    }
                }
                if($lineno !== null) $selectfs['keywords'][strval($lineno)] = '';
            }
            else{
                if('fid=' == substr($rule,0,4)){
                    $tno = substr($rule, 4);
                    if (is_numeric($tno)) $tno = (int)$tno;
                    if(!isset($selectfs['fid'])) $selectfs['fid'] = array($tno);
                    elseif(!in_array($tno,$selectfs['fid'])) $selectfs['fid'][] = $tno;
                }
            }
        }
        $theadext_table = null;
        $fid = 0;
        //填充匹配备件:
        if(!empty($selectfs)){
            $post_row = db_find_one('post', array('pid' => $pid,'isfirst'=>1),array(),array('tid'));
            if(!empty($post_row)){
                $tid = (int)$post_row['tid'];
                $thread_row = db_find_one('thread', array('tid' => $tid),array(),array('fid'));
                if(!empty($thread_row) && isset($selectfs['fid'])) {
                    $fid = (int)$thread_row['fid'];
                    $asr = array_search(0,$selectfs['fid']);
                    if($asr !== null && $asr !== false){
                        $selectfs['fid'][$asr] = $fid;
                    }
                    if(count($selectfs['fid']) == 1)//只有一个,转化为值
                        $selectfs['fid'] = $selectfs['fid'][0];
                }
                if(isset($selectfs['keywords'])){
                    global $ghx_cache;
                    $theadext_table = $ghx_cache->get_share_var(VAR_THREADEXT_TB);
                    $theadext_row = db_find_one($theadext_table, array('tid' => $tid),array(),array('keywords'));
                    if(!empty($theadext_row)){
                        $keys = preg_split('/[\s,;\|]+/u',$theadext_row['keywords']);
                        $delfs = array();
                        foreach($selectfs['keywords'] as $fidx => &$fv){
                            if(is_numeric($fidx)){
                                $fidi = intval($fidx);
                                if($fidi < 0){
                                    $fidi = count($keys) + $fidi;
                                }
                                if($fidi >= count($keys) || empty($keys[$fidi])){
                                    $delfs[] = $fidx;//无效的删除
                                }
                                else{
                                    $fv = $keys[$fidi];
                                }
                            }
                        }
                        foreach($delfs as $delf){
                            unset($selectfs['keywords'][$delf]);
                        }
                        if(empty($selectfs['keywords'])) unset($selectfs['keywords']);
                    }
                }
            }
            else
                $selectfs = null;
        }
        //从数据库查询:
        if(!empty($selectfs)){
            $conds = array();
            $threads = $vpids = null;
            $postflag_table = $ghx_cache->get_share_var(VAR_POSTFLAG_TB);
            if(isset($selectfs['fid'])){
                //$selectfs['fid'] 可能是数组.查询条件:fid;主题贴;非隐藏
                $vpids = db_find($postflag_table, array('fid' => $selectfs['fid'],'isfirst'=>1,'hide'=>0),array(),1,PHP_INT_MAX>>2,'tid',array('tid','pid'));
                if(!empty($vpids)){//获取到所有指定fid的tid
                    $conds['tid'] = array();
                    foreach($vpids as &$vpid){
                        $vtid = intval($vpid['tid']);
                        if($vtid > 0 && !in_array($vtid,$conds['tid'])){
                            $conds['tid'][] = $vtid;
                        }
                    }
                    unset($vpid);
                }
                else
                    $conds = null;
            }
            if(isset($selectfs['keywords'])){
                if($conds !== null) {
                    $myfields = array('keywords', 'tid');
                    $rows = db_count($theadext_table, $conds);
                    if ($rows > 0) {
                        $pages = 0;
                        $ret2 = array();
                        do {
                            $dbrs = db_find($theadext_table, $conds, array(), $pages++, $MAX_ONCE_READ, 'tid', $myfields);
                            $reads = 0;
                            if (!empty($dbrs)) {
                                foreach ($dbrs as $dbtid => &$dbv) {
                                    $reads++;
                                    if($dbtid == $tid) continue;
                                    if (!empty(trim($dbv['keywords']))) {
                                        $mykeys = preg_split('/[\s,;\|]+|\s{2,}/u', $dbv['keywords']);
                                        $mykeys_c = count($mykeys);
                                        if (isset($selectfs['keywords']['value'])) {
                                            if (!in_array($selectfs['keywords']['value'], $mykeys)) {
                                                continue;
                                            }
                                        }
                                        foreach ($selectfs['keywords'] as $p => &$kv) {
                                            if (ctype_digit($p)) {
                                                $pi = intval($p);
                                                if ($pi < 0) $pi += $mykeys_c;
                                                if ($pi >= $mykeys_c || $mykeys[$pi] != $kv) continue 2;
                                            }
                                        }
                                        $ret2[$dbv['tid']] = &$dbv;
                                    }
                                }
                            }
                        } while ($reads >= $MAX_ONCE_READ);
                        //填充pid:
                        if(!empty($vpids)) {//指定了fid的情况:
                            foreach ($ret2 as $dbtid => &$dbr2) {
                                $curPid = (int)$vpids[$dbtid]['pid'];
                                $dbr2['pid'] = $curPid;
                                if ($pid != $curPid) $ret[$curPid] = &$dbr2;//排除本身
                            }
                            unset($dbr2);
                        }
                        else {//只指定了keywords的情况:
                            $tids = array_keys($ret2);
                            $conds = array('tid' => $tids, 'isfirst' => 1);
                            $dbrs2 = db_find('post', $conds, array(), 1, count($tids), 'tid', array('tid', 'pid'));
                            if (!empty($dbrs2)) {
                                foreach ($dbrs2 as $dbtid => &$dbr2) {
                                    $curPid = (int)$dbr2['pid'];
                                    $optr = &$ret2[(int)$dbr2['tid']];
                                    $optr['pid'] = $curPid;
                                    if ($pid != $curPid) $ret[$curPid] = &$optr;//排除本身
                                    unset($optr);
                                }
                            }
                        }
                    }
                }
            }
            elseif(isset($selectfs['fid']) && !empty($vpids)){
                foreach($vpids as &$vpid){
                    $curPid = $vpid['pid'];
                    if($pid != $curPid) $ret[$curPid] = &$vpid;
                }
                unset($vpid);
            }
        }
    }
    if(!empty($ret) || $selectfs === null) $retarr[$md5] = &$ret;
    return $ret;
}

/**
 * 合并结果参数(后者会覆盖前者)
 * @param array &$obj 要合并的数组对象
 * @param array &$params 结果数组
 * @param null $para_key 合并到结果数组中指定的键名,默认为null
 * @param bool $try_root_key 是否测试$para_key是滞为根键名
 * @param bool $obj_key_ambiguous_assoc is_assoc_array()有歧义时是否视为有意义的键名,默认为true
 * @return int 返回成功合并的数量
 */
function merge_parameters(array &$obj,array &$params,$para_key=null,bool $try_root_key=false,$obj_key_ambiguous_assoc=true){
    $merges = 0;
    if($obj != null && $params !== null){
        $result = null;
        if($try_root_key && !empty($para_key)){
            global $valid_cmd;
            if(in_array(key($obj),$valid_cmd))
                $para_key = null;
        }
        if($para_key != null){
            if(!isset($params[$para_key]))
                $params[$para_key] = array();
            $result = &$params[$para_key];
        }
        else
            $result = &$params;
        $is_assoc = null;
        if(!empty($para_key)) $is_assoc = is_assoc_array($obj,'key',8,$obj_key_ambiguous_assoc);
        foreach($obj as $k => &$v){//$k:pid|flag
            if(empty($para_key)) {//根目录
                if(!isset($params[$k]))  $params[$k] = array();
                $is_assoc = is_assoc_array($v,'key',8,$obj_key_ambiguous_assoc);
                foreach($v as $k2 => &$v2){//$k:pid,$k2:flag
                    if($is_assoc){
                        if(!array_key_exists($k2, $result[$k])|| empty($result[$k][$k2])) {
                            $result[$k][$k2] = &$v2;
                            $merges++;
                        }
                    }
                    else{
                        if(!in_array($v2,$result[$k])){
                            $result[$k][] = &$v2;
                            $merges++;
                        }

                    }
                }
            }
            else{
                if($is_assoc){
                    if(!array_key_exists($k, $result) || empty($result[$k])){
                        $result[$k] = &$v;
                        $merges++;
                    }

                }
                else{
                    if(!in_array($v,$result)){
                        $result[] = &$v;
                        $merges++;
                    }
                }
            }
        }
    }
    return $merges;
}

/**
 * 将字符串参数转化为标准格式参数,array({key}=>{opt}),输出如下格式:
 * 'postflag'=>array({pid}=>array({flat}=>{reason}...))
 * 'clear'=>array({pid}=>array({flag}...)...)
 * 'striphtml'=>array({pid_list}=>{preserve}...)
 * 'getinfo'=>array({pid}=>array({field}...)...)
 * @param array $paras 字符串参数混合体
 * @param int $default_pid 默认的pid
 * @param string|array &$first_dafult_val $paras中第一个空值的补缺值
 * @param string $WebRequestDataDelimiter 符串参数分隔符,第0个为键值分隔符,第1个为第一层次的分隔符,以此类推,默认为':|;,'
 * @param array &$PostFlags 标记配置数组
 * @return array
 */
function &parse_commands(array $paras, int $default_pid, &$first_dafult_val, $WebRequestDataDelimiter = ':|;,', array &$PostFlags = null)
{
    global $valid_cmd,$valid_actives;
    if ($PostFlags === null) {
        global $PostFlagCfg;
        $PostFlags = &$PostFlagCfg['Flags'];
    }
    $planers = array();//生成的结果
    if (!empty($paras) && !empty($PostFlags)) {
        $max_nesting_depth = 16;//最大的嵌套深度
        $cmds = array_keys($paras);
        for ($pk = 0; $pk < count($cmds); $pk++){
            if ($max_nesting_depth < 0) break;//超过最大嵌套深度,直接跳出
            $k = $cmds[$pk];//$k:cmd
            if (empty($paras[$k]) && isset($first_dafult_val) && !empty($first_dafult_val)) {//加载默认值
                $paras[$k] = &$first_dafult_val;
                unset($first_dafult_val);//断掉关联
            }
            $paras_val = &$paras[$k];
            if(empty($paras_val)){//将空参数删除
                unset($paras[$k]);
                $cmds = array_keys($paras);
                $pk--;
                continue;
            }
            $merge_obj = null;
            //散装flag,暂存到$planers['postflag']:
            if (!is_numeric($k) && isset($PostFlags[$k])) {
                if(!isset($planers['postflag'])) $planers['postflag'] = array();
                if (!isset($planers['postflag'][$default_pid])) $planers['postflag'][$default_pid] = array();
                $myref = array($k=>&$paras_val);
                merge_parameters($myref,$planers['postflag'][$default_pid]);
                unset($paras[$k]);
                $cmds = array_keys($paras);
                $pk--;
                continue;
            }
            $paras_itme_is_array = is_array($paras_val);
            if (!$paras_itme_is_array) {
                $opt_paras = array(&$paras_val);//仍然有可能有batch
            } else {
                if ($k == 'batch') {//释放到上一层并重新开始
                    $parse_clear = array();
                    $parse_clear_reset = 0;
                    foreach ($paras_val as $p_k => &$p_v) {
                        if (in_array($p_k, $valid_cmd)) {
                            if (!isset($paras[$p_k])) {
                                $paras[$p_k] = &$p_v;
                            } else {
                                if (!is_array($paras[$p_k]))
                                    $paras[$p_k] = array($paras[$p_k]);
                                if (!in_array($p_v, $paras[$p_k]))
                                    $paras[$p_k][] = &$p_v;//简单追加
                            }
                            $parse_clear[] = $p_k;
                            $parse_clear_reset++;
                        } else {
                            if (!is_numeric($p_k) && isset($PostFlags[$p_k])) {//散装postflag:
                                if(!isset($planers['postflag'])) $planers['postflag'] = array();
                                if (!isset($planers['postflag'][$default_pid])) $planers['postflag'][$default_pid] = array();
                                $merge_obj = &$planers['postflag'][$default_pid];
                                if (!array_key_exists($p_k, $merge_obj) || !empty($p_v))
                                    if (is_array($p_v))
                                        $merge_obj[$p_k] = implode(',', $p_v);
                                    else
                                        $merge_obj[$p_k] = strval($p_v);//替换或者新增
                                $parse_clear[] = $p_k;
                            }
                        }
                    }
                    foreach ($parse_clear as $pck) {
                        unset($paras_val[$pck]);
                    }
                    unset($parse_clear);
                    $max_nesting_depth--;
                    if (empty($paras_val)) {//batch可能还是存在，字符串形式的
                        unset($paras[$k]);
                        $cmds = array_keys($paras);
                        if ($parse_clear_reset > 0) $pk = -1;
                        else $pk--;
                        continue;
                    }
                } else
                    $opt_paras = &$paras_val;
            }
            //一种cmd可能有多组
            $opt_paras_keys = array_keys($opt_paras);
            foreach ($opt_paras_keys as &$pid_try){
                $opt_para = &$opt_paras[$pid_try];
                if (is_string($opt_para)) {
                    $opt_para_len = strlen($opt_para);
                    if ($opt_para_len > 7 && $opt_para{0} == '{' && $opt_para{$opt_para_len - 1} == '}') {
                        $opt_para = xn_json_decode($opt_para);
                        if(is_array($opt_para)){
                            if(in_array(key($opt_para),$valid_cmd)) {//与根参数合并
                                unset($opt_paras[$pid_try]);
                                if(!$paras_itme_is_array) unset($paras[$k]);
                                if(merge_parameters($opt_para,$paras) > 0 || !$paras_itme_is_array) {
                                    $cmds = array_keys($paras);
                                    $pk = -1;
                                    continue 2;
                                }
                                else
                                    continue;
                            }
                            else
                                merge_parameters($opt_para,$planers,$k,true);
                        }
                    }
                    else{
                        if ($k == 'postflag') {//没有指定pid,直接存于$planers:
                            if (!is_numeric($pid_try)) {
                                if (isset($PostFlags[$pid_try])) {
                                    if(!isset($planers['postflag'])) $planers['postflag'] = array();
                                    if (!isset($planers['postflag'][$default_pid])) $planers['postflag'][$default_pid] = array();
                                    $myref = array($pid_try=>&$opt_para);
                                    merge_parameters($myref,$planers['postflag'][$default_pid]);
                                }
                                //删除已经处理过的:
                                unset($opt_paras[$pid_try]);
                                if (!$paras_itme_is_array || empty($opt_paras)){
                                    unset($paras[$k]);
                                    $cmds = array_keys($paras);
                                    $pk--;
                                    continue 2;
                                }
                                else
                                    continue;
                            }
                            //之后还有postflag
                        }
                        elseif($k == 'clear' || $k == 'striphtml'){
                            if (empty($opt_para) && is_numeric($pid_try)){
                                $empty_pid = $pid_try;
                                if(!$paras_itme_is_array) $empty_pid = $default_pid;
                                if(!array_key_exists($empty_pid,$planers[$k]))
                                    $planers[$k][$pid_try] = '';
                                unset($opt_paras[$pid_try]);
                                if (!$paras_itme_is_array || empty($opt_paras)){
                                    unset($paras[$k]);
                                    $cmds = array_keys($paras);
                                    $pk--;
                                    continue 2;
                                }
                                else
                                    continue;
                            }
                        }
                    }
                    $is_pid_postflag = null;//$k是为postflag操作的pid
                    $cmd_keys = null;
                    if (is_numeric($pid_try) || ($k == 'flags')) {
                        switch ($k) {
                            case 'batch':
                                $cmd_keys = array('cmd' => array('keytype' => 'string', 'defaultkey' => false, 'defaultval' => false));
                                break;
                            case 'clear'://清除,包含pid => array(flags)
                                $cmd_keys = array('pid' => array('keytype' => 'int', 'defaultkey' => $default_pid, 'defaultval' => false), 'flag' => array('keytype' => 'string', 'onlyvalue' => true, 'defaultval' => false));
                                break;
                            case 'striphtml'://删除HTML标签,包含list和preserve?键名
                                $cmd_keys = array('list' => array('keytype' => 'string', 'defaultkey' => $default_pid, 'defaultval' => ''));
                                break;
                            case 'getinfo'://获取标记详情,格式:pid:field,field2,field3;pid2:field;
                                $cmd_keys = array('pid' => array('keytype' => 'int', 'defaultkey' => $default_pid, 'defaultval' => false), 'field' => array('keytype' => 'string', 'onlyvalue' => true, 'defaultval' => false));
                                break;
                            case 'flags':
                                if (is_numeric($pid_try))//多标记操作,包含pid => array({flag}=>{reason}...),{reason}可能为空
                                    $cmd_keys = array('pid' => array('keytype' => 'int', 'defaultkey' => $default_pid, 'defaultval' => false), 'flag' => array('keytype' => 'string', 'defaultval' => ''));
                                else//非常规格式：'flags'=》array('pid1:原因1;pid2:原因2;',...)
                                    $cmd_keys = array('list' => array('keytype' => 'int', 'onlyvalue' => true, 'defaultval' => false), 'flag' => array('keytype' => 'int', 'defaultval' => ''));
                                break;
                            case 'postflag'://必须包含pid:标记内容,处理前格式:{reason};生成格式:array({pid}=>array({flag}=>{reason})),{reason}可能为空
                                $cmd_keys = array('pid' => array('keytype' => 'int', 'defaultkey' => $default_pid, 'defaultval' => false), 'flag' => array('keytype' => 'string', 'defaultval' => ''));
                                break;
                            default:
                                if (is_numeric($k)) {//$k为pid,等处理格式:{flag}:{reason}|{flag2}:{reason2}...
                                    if (!empty($opt_para)) {
                                        $cmd_keys = array('flag' => array('keytype' => 'string', 'defaultkey' => false, 'defaultval' => ''));
                                        $is_pid_postflag = true;
                                    }
                                }
                                break;
                        }
                        if (!empty($cmd_keys)) {
                            if (is_string($opt_para) && !empty($opt_para)) {
                                $opt_para = &parse_web_request_data_items($opt_para, $WebRequestDataDelimiter, $cmd_keys);
                                if (!empty($opt_para) && is_array($opt_para)) {
                                    if ($k === 'flags' || $is_pid_postflag) {//flags:
                                        if($is_pid_postflag){
                                            $opt_para2 = &$opt_para;
                                            unset($opt_para);
                                            $opt_para = array($k => &$opt_para2);
                                            unset($opt_para2);
                                        }
                                        foreach ($opt_para as $ox => &$oxv) {
                                            $ox_pid = $ox;
                                            if (!is_numeric($pid_try)) $ox_pid = $default_pid;//$pid_try是flag
                                            if (!isset($planers['postflag'])) $planers['postflag'] = array();
                                            if (!isset($planers['postflag'][$ox_pid])) $planers['postflag'][$ox_pid] = array();
                                            foreach ($oxv as $o2k => &$o2v) {
                                                //合并:
                                                if (!empty($o2v) || !array_key_exists($o2k, $planers['postflag'][$ox_pid])) {
                                                    $planers['postflag'][$ox_pid][$o2k] = &$o2v;
                                                }
                                            }
                                        }
                                    }
                                    else{
                                        if(in_array($k,$valid_actives)){
                                            merge_parameters($opt_para,$planers,$k);
                                        }
                                        else{//batch:
                                            if($k === 'batch'){
                                                $max_nesting_depth--;
                                                if(merge_parameters($opt_para,$paras,null,false,false) > 0){
                                                    unset($opt_paras[$pid_try]);
                                                    if (!$paras_itme_is_array || empty($opt_paras)){
                                                        unset($paras[$k]);
                                                        $cmds = array_keys($paras);
                                                        $pk = -1;
                                                        continue 2;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else {
                    if (is_array($opt_para) && !empty($opt_para)) {//只录取效的参数
                        if(!isset($planers[$k])) $planers[$k] = array();
                        merge_parameters($opt_para,$planers[$k],$pid_try);
                    }
                }
                //清除处理过的
                unset($opt_paras[$pid_try],$opt_para,$pid_try);
                if (!$paras_itme_is_array || empty($opt_paras)){
                    unset($paras[$k]);
                    $cmds = array_keys($paras);
                    $pk--;
                    continue 2;
                }
            }

            unset($paras[$k]);
            $cmds = array_keys($paras);
            $pk--;
        }
    }
    return $planers;
}

/**
 * 检测指定用户在某post上是否有ManagePostFlag权限
 * @param int $pid post id
 * @param array &$flags 要测试的postflag表,为空时返回指定pid的父级目录表
 * @param int $uid
 * @param int $gid 用户组ID
 * @param array $EnablePostFlags
 * @param array $EnablePostFlagsSelf
 * @param bool $allow_partial_failure 是否允许部分失败,如果允许,那么则修改$flags参数
 * @param array $post_parents0 输出指定pid的父级目录表,是用array()包装的:array({pid}=>&$post_parents),注:也可以当成输入数组,此时,输出不改变形态
 * @return bool|array
 */
function &ValidManagePostFlagForPostAuth(int $pid, array &$flags, int $uid, int $gid, array &$EnablePostFlags, array &$EnablePostFlagsSelf, $allow_partial_failure = false, array &$post_parents0 = null)
{
    static $posts_catalogs = array();
    $cur_post_parents = null;
    if (!isset($posts_catalogs[$pid])) {
        if(is_array($post_parents0) && isset($post_parents0[$pid]) && is_array($post_parents0[$pid])){
            $posts_catalogs[$pid] = &$post_parents0[$pid];
            $cur_post_parents = &$posts_catalogs[$pid];
        }
        else {
            $cur_post_parents = &GetInfoCatalogWithOwn(TX_INFO_TYPE_POST, $pid);
            if (!empty($cur_post_parents)) {//不存在的pid
                $posts_catalogs[$pid] = &$cur_post_parents;
            }
        }
    } else
        $cur_post_parents = &$posts_catalogs[$pid];
    //权限验证:
    $is_valid = false;
    if (!empty($cur_post_parents)) {
        if(!is_array($post_parents0))
            $post_parents0 = array($pid => &$cur_post_parents);
        elseif(!isset($post_parents0[$pid]))
            $post_parents0[$pid] = &$cur_post_parents;
        if(empty($flags))
        {
            return $cur_post_parents;//只取指定pid的父级目录表
        }
        if (forum_access_user($cur_post_parents['fid'], $gid, 'allowpost')) {//普通用户权限判断
            if (forum_access_mod($cur_post_parents['fid'], $gid, 'allowtop') || forum_access_mod($cur_post_parents['fid'], $gid, 'allowupdate')) {//板块斑竹权限判断,管理标记必须有置顶或者修改的权限
                $v_flag = array();
                $key_is_flag = !is_numeric(key($flags));
                foreach ($flags as $k => &$v) {
                    $flag = $k;
                    if(!$key_is_flag) $flag = &$v;
                    if (isset($EnablePostFlags[$flag]) || (isset($cur_post_parents['uid']) and $uid === $cur_post_parents['uid'] and isset($EnablePostFlagsSelf[$flag]))) {//是否拥有此标记权限
                        if($key_is_flag)
                            $v_flag[$flag] = &$v;
                        else
                            $v_flag[] = &$flag;
                    }
                    unset($flag);
                }
                if (count($v_flag) == count($flags))
                    $is_valid = true;
                elseif ($allow_partial_failure && !empty($v_flag)) {//如果是全部分清除,则允许部分失败
                    $flags = array();//清除
                    foreach ($v_flag as $kf => &$vf) {
                        $flags[$kf] = &$vf;
                    }
                    $is_valid = true;
                }
                unset($v_flag);
            }
        }
    }
    return $is_valid;
}
function GetIsFirstPostSet(array &$pfcfg,$pid){
    $ret = 0;
    if(!empty($pfcfg)){
        if(isset($pfcfg[$pid])) $ret = $pfcfg[$pid];
        elseif(isset($pfcfg[0]))  $ret = $pfcfg[0];
    }
    return $ret;
}
//region 环境参数读取
$reqcmd = param(1, '');//指令代码
$pid = param(2, 0);//$_POST里或者自身的参数内的pid优先取用
$channel = param(3, '');//频道或者对象,第二个参数
$ispostfirst = param('isfirst');//是否作为为主贴处理的数组,可以是多种格式,一般格式:{pid}:0;{pid2}:1;...处理后的结果:array({pid}=>{value}...);如果没有指定pid,则为0,即未规定的其它情况
//endregion
//region 全局执行参数
$optret = 0;
$addflags = array();//成功添加的标记,格式:pid=>array(flags)
$delflags = array();//成功删除的标记,格式:pid=>array(flags)
$otheropt = array();//其它成功执行的操作,格式:pid=>array(msg)
$message_fmt_chg = array();//针对striphtml操作返回的结果
$getinfo_ret = array();
$firstpost_fs = array();//存储主贴的postflag数据
$_curGid = intval($gid);
$_curUid = intval($uid);
$order_data = _POST('orders', '');
$succopt = 0;//操作成功次数
//endregion

user_login_check();
if ($method == 'POST') {//禁止URL直接访问
    //有效的请求指令
    if (GetPostFlagEnable()) {
        //region 基本参数设置
        $PostFlagNodesCfg = &$PostFlagCfg['Flags'];
        $PostFlagTable = $PostFlagCfg['table'];
        $web_request_data_delimiter = $PostFlagCfg['WebRequestDataDelimiter'];
        $optCmds = null;
        //处理主贴配置记录
        if(!is_array($ispostfirst)) {
            if (!empty($ispostfirst)) {
                if (is_numeric($ispostfirst)) $ispostfirst = array(intval($ispostfirst));
                else {
                    $ispostfirst_len = strlen($ispostfirst);
                    if ($ispostfirst_len > 7 && $ispostfirst{0} == '{' && $ispostfirst{$ispostfirst_len - 1} == '}')
                        $ispostfirst = xn_json_decode($ispostfirst);
                    else {
                        $pfarr = &explode_chr_head_tail($ispostfirst, ';');
                        $ispostfirst = array();
                        foreach ($pfarr as $pfitr) {
                            $pfitr2 = explode(':', $pfitr, 2);
                            if ($pfitr2 != false && count($pfitr2)) {
                                if (ctype_digit($pfitr2[0])) {
                                    $fv_0 = 0;
                                    $fv_s = strtolower($pfitr2[1]);
                                    if ($fv_s == 'true' || $fv_s == 'yes') {
                                        $fv_0 = 1;
                                    } else {
                                        $fv_0 = intval($fv_s);
                                    }
                                    $ispostfirst[$pfitr2[0]] = $fv_0;
                                }
                            }
                        }

                    }
                }
                if (empty($ispostfirst)) $ispostfirst = array(0);
            } else
                $ispostfirst = array(0);
        }
        //endregion
        $is_valid_cmd = in_array($reqcmd,$valid_cmd);
        if($is_valid_cmd || isset($PostFlagNodesCfg[$reqcmd])) {
            //region 组装参数:
            $default_pid = _POST('pid', 0);
            if ($default_pid == 0)
                $default_pid = $pid;
            if (!empty($order_data) && $is_valid_cmd)
                $optCmds = array($reqcmd => &$order_data);
            else {
                switch ($reqcmd) {
                    case 'getinfo':
                    case 'striphtml':
                    case 'clear':
                        if ($reqcmd == 'striphtml') {
                            $pid = param(2, '');
                            if (is_numeric($pid)) $pid = intval($pid);
                        }
                        $optCmds = array($reqcmd => $pid . ':' . $channel);
                        break;
                    case 'flags':
                    case 'postflag':
                        $optCmds = array($reqcmd => array($pid => array($channel => '')));
                        break;
                    case 'batch':
                        $optCmds = array($reqcmd => $channel);
                        break;
                    default://flag:
                        $optCmds = array('postflag' => array($pid => array($reqcmd => $order_data)));
                        break;
                }
            }
            //格式化参数:
            $default_d_v = '';
            //endregion
            $optStdCmds = &parse_commands($optCmds, $default_pid, $default_d_v, $web_request_data_delimiter, $PostFlagNodesCfg);
            if (!empty($optStdCmds)) {
                //region 运行参数设置
                $UniqueFlags = array();//唯一标记登记表,结构:array({tid}=>array({flag}=>array({pid}=>{reason}))...)
                $updates = array();
                $orderqueues = array();
                $clearFlagSql = array();
                $postflag_olds = array();//结构: array({pid}=>array(data))
                $clearUnique = array();//结构:array({pid}=>array({flag}=>array('upd'=>array('cond'=>array(),'update'=>array()),'execsql'=>{sql}))...)
                $ManagePostFlagCfg = GetViewPostFlags($_curGid, 'manage', true);
                $MarkPostFlagCfg = GetViewPostFlags($_curGid, 'mark', true);
                $ManagePostFlagCfg1 = array_expand($ManagePostFlagCfg, 2);
                $MarkPostFlagCfg1 = array_expand($MarkPostFlagCfg, 2);
                $EnablePFlags = $EnablePFlagsSelf = null;//用于权限验证
                $clear_flag_pid_def = $striphtml_pid_def = $getinfo_pid_def = false;
                //处理$optFlags,同组只取最后一个,但需要参考reason,有reason者优先
                $opt_Flags = array();
                $optCmdKeys = array_keys($optStdCmds);
                $optCmdKey_len = count($optCmdKeys);
                $optCmdVal = null;
                //endregion
                //操作过滤
                for ($ofi = 0; $ofi < $optCmdKey_len; $ofi++) {
                    $curCmd = $optCmdKeys[$ofi];
                    if ($optCmdVal !== null) unset($optCmdVal);//脱钩
                    $optCmdVal = &$optStdCmds[$curCmd];
                    if ($EnablePFlags === null && $curCmd != 'striphtml' && $curCmd != 'getinfo') {
                        $EnablePFlags = &ListValidPostFlags('Auth', $_curGid);
                        $EnablePFlagsSelf = &ListValidPostFlags('Auth', $_curGid, true);
                    }
                    //cmd是否有效:
                    $is_discard = false;
                    if (!in_array($curCmd, $valid_actives)) {
                        $is_discard = true;
                    } elseif ($curCmd == 'striphtml' && ($_curGid < 1 || $_curGid > 5)) {
                        $is_discard = true;
                    }

                    //flag是否有效:
                    $ck_grandson_flag = ($curCmd == 'getinfo' || $curCmd == 'clear' || $curCmd == 'postflag');
                    if (!$is_discard && $ck_grandson_flag) {//第二级上的flag检查:
                        $unset_pids = array();
                        foreach ($optCmdVal as $fp_pid => &$fp_flags_val) {
                            $group_placeholder = array();//分组占位
                            $unset_flags = array();
                            foreach ($fp_flags_val as $ck_flag => &$ck_flag_val) {
                                $del_flag = false;
                                $ck_f_k = &$ck_flag;
                                if (is_numeric($ck_f_k)) {
                                    $ck_f_k = &$ck_flag_val;
                                }
                                $ck_f_k2 = strtolower($ck_f_k);
                                if (!isset($PostFlagNodesCfg[$ck_f_k]) && $ck_f_k != '*' && $ck_f_k2 != 'all') {
                                    $unset_flags[] = $ck_flag;
                                    $del_flag = true;
                                } else {
                                    if ($curCmd != 'getinfo') {
                                        //基本权限验证
                                        if (!isset($ManagePostFlagCfg1[$ck_f_k]) || (!isset($EnablePFlags[$ck_f_k]) && !isset($EnablePFlagsSelf[$ck_f_k]))) {
                                            if ($curCmd != 'clear' || ($ck_f_k != 'all' && $ck_f_k != '*' )) {
                                                $unset_flags[] = $ck_flag;
                                                $del_flag = true;
                                            }
                                        }
                                    }
                                    if (!$del_flag && $curCmd == 'postflag') {
                                        if ($ck_f_k != '*' && $ck_f_k2 != 'all') {
                                            $fg1 = $PostFlagNodesCfg[$ck_f_k]['Group'];//分组过滤:
                                            if (!isset($group_placeholder[$fg1]) || empty($group_placeholder[$fg1]))
                                                $group_placeholder[$fg1] = array($ck_flag => &$ck_flag_val);
                                            else {
                                                if (empty($ck_flag_val) && !empty(current($group_placeholder[$fg1]))) {
                                                    $unset_flags[] = $ck_flag;//把目前这个没有reason的删除
                                                    $del_flag = true;
                                                }
                                                if (!$del_flag) {
                                                    $unset_flags[] = key($group_placeholder[$fg1]);//删除前加入的
                                                    $group_placeholder[$fg1] = array($ck_flag => &$ck_flag_val);//只取最后一个,同组只取一个
                                                }
                                            }
                                        } else
                                            $del_flag = true;
                                    }
                                }
                                unset($ck_f_k);
                            }
                            unset($ck_flag_val);
                            if (!empty($unset_flags)) {
                                foreach ($unset_flags as &$unset_flag) {
                                    unset($fp_flags_val[$unset_flag]);
                                }
                                if (empty($fp_flags_val)) {
                                    $unset_pids[] = $fp_pid;
                                }
                            }
                        }
                        if (!empty($unset_pids)) {
                            foreach ($unset_pids as &$unset_pid) {
                                unset($optCmdVal[$unset_pid]);
                            }
                            unset($unset_pid);
                            if (empty($optCmdVal)) {//删空了
                                $is_discard = true;
                            }
                        }
                    }
                    if ($is_discard) {
                        unset($optStdCmds[$curCmd]);
                        $optCmdKeys = array_keys($optStdCmds);
                        $optCmdKey_len--;
                        $ofi--;
                    }
                }

                $optCmdKeys = array_keys($optStdCmds);
                $optCmdKey_len = count($optCmdKeys);
                //设置与基本权限验证已经完成筛选
                $opt_order = null;
                //生成操作队列:
                for ($ofi = 0; $ofi < $optCmdKey_len; $ofi++) {
                    //清除前值:
                    if ($opt_order !== null) unset($opt_order);
                    //初始化:
                    $curCmd = &$optCmdKeys[$ofi];
                    $opt_order = &$optStdCmds[$curCmd];
                    switch ($curCmd) {
                        case 'clear'://清除标记
                            foreach ($opt_order as $_pid => &$clearpflags) {
                                if (!is_numeric($_pid)) continue;
                                $_pid = intval($_pid);
                                if ($_pid < 1 || empty($clearpflags)) continue;
                                $isfirst = GetIsFirstPostSet($ispostfirst,$_pid);
                                $postflag_cur = db_find_one($PostFlagTable, array('pid' => $_pid,'isfirst'=>$isfirst));
                                if (!empty($postflag_cur)) {
                                    if (!isset($postflag_olds[$_pid])) {
                                        $postflag_olds[$_pid] = &$postflag_cur;
                                    }
                                    $clearAll = false;
                                    if (is_string($clearpflags) && ($clearpflags == '*' || strtolower($clearpflags) == 'all'))
                                        $clearAll = true;//全部删除:
                                    elseif (is_array($clearpflags) && ($clearpflags[0] == '*' || strtolower($clearpflags[0]) == 'all'))
                                        $clearAll = true;//全部删除:
                                    if ($clearAll) {//具体化$clearpflags
                                        $clearpflags = array();
                                        foreach ($postflag_cur as $pffk => &$pffv) {
                                            if (!empty($pffv)) {
                                                if (substr($pffk, -2) == '_u') {
                                                    $clearpflags[] = substr($pffk, 0, -2);
                                                }
                                            }
                                        }
                                    }
                                    if (!ValidManagePostFlagForPostAuth($_pid, $clearpflags, $_curUid, $_curGid, $EnablePFlags, $EnablePFlagsSelf, true)) {
                                        continue;//没要需要的权限,或者部分被限制
                                    }
                                    foreach ($clearpflags as $del_pf){
                                        if ($_curGid != 0 && $postflag_cur[$del_pf . '_g'] != 0 && isset($ManagePostFlagCfg1[$del_pf])){
                                            //隐藏的可以直接操作,不需要检查Unique
                                            if ($postflag_cur['hide'] > 0 || ($postflag_cur[$del_pf . '_g'] > $_curGid || (($postflag_cur[$del_pf . '_u'] == $_curUid) && ($postflag_cur[$del_pf . '_g'] == $_curGid)))) {
                                                if(!isset($clearFlagSql[$_pid]))
                                                    $clearFlagSql[$_pid] = array('upd' => array(), 'chgord' => 0);
                                                $clearFlagSql[$_pid]['upd'][$del_pf] = '';
                                                $clearFlagSql[$_pid]['upd'][$del_pf . '_g'] = 0;
                                                $clearFlagSql[$_pid]['upd'][$del_pf . '_u'] = 0;
                                                if ($PostFlagNodesCfg[$del_pf]['order'] != 0) {//注意firstpost的情况:
                                                    $clearFlagSql[$_pid]['chgord'] += $PostFlagNodesCfg[$del_pf]['order'];
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            break;
                        case 'striphtml'://去掉HTML标签
                            $striphtml_pids = null;
                            foreach ($opt_order as $striphtml_pids => $preserve) {
                                if (empty($striphtml_pids)) continue;
                                $sh_pids = preg_split('/[\s,;\\\\\/]+/s', $striphtml_pids);
                                foreach ($sh_pids as $_pid) {
                                    $_pid = intval($_pid);
                                    if ($_pid < 1) continue;
                                    //获取回复内容:
                                    $post_cur = db_find_one('post', array('pid' => $_pid), array(), array('message_fmt'));
                                    if (!empty($post_cur)) {
                                        $message_fmt = &$post_cur['message_fmt'];
                                        $message_2 = strip_html($message_fmt, true, $preserve);
                                        if ($message_fmt != $message_2) {
                                            //更新数据库:
                                            if (db_update('post', array('pid' => $_pid), array('message_fmt' => $message_2)) > 0) {
                                                if (!isset($otheropt[$_pid])) $otheropt[$_pid] = array();
                                                $message_fmt_chg[$_pid] = $message_2;
                                                $otheropt[$_pid][] = '清除了帖子[' . $_pid . ']的格式.';
                                                $succopt++;
                                            }
                                        }
                                        unset($message_fmt);
                                    }
                                }
                            }
                            break;
                        case 'getinfo':
                            if (!empty($opt_order) && is_array($opt_order)) {
                                //解析pid:
                                foreach ($opt_order as $pf_id => &$pf_fs) {
                                    $pf_idn = intval($pf_id);
                                    if ($pf_idn < 1 || empty($pf_fs)) {
                                        continue;
                                    }
                                    //字段检查:
                                    $flagcols = &GhxCache::getInstance()->get_share_var(VAR_TABLE_COLUMNS, $PostFlagTable);
                                    if (!empty($flagcols)) {
                                        $flagcols1 = array();
                                        foreach ($flagcols as $fck => &$fckv) {
                                            $end2 = substr($fck, -2);
                                            if ($fck != 'hide' && $end2 != '_u' && $end2 != '_g') {
                                                $flagcols1[] = $fck;
                                            }
                                        }
                                        if ($pf_fs[0] == 'all' || $pf_fs[0] == '*') {
                                            $pf_fs = $flagcols1;
                                        } else {
                                            if (!in_array('pid', $pf_fs)) $pf_fs[] = 'pid';
                                            $pf_fs = array_intersect($flagcols1, $pf_fs);
                                        }
                                        $postFlagInfo = db_find_one($PostFlagTable, array('pid' => $pf_idn), array(), $pf_fs);
                                        if (!empty($postFlagInfo)) {
                                            $getinfo_ret[$pf_idn] = &$postFlagInfo;
                                            $succopt++;
                                        }
                                        unset($postFlagInfo);
                                    }

                                }
                            }
                            break;
                        case 'postflag'://{pid}=>array({flag}=>{reason}...)
                            foreach ($opt_order as $pf_pid => &$useflags) {
                                if (ctype_digit($pf_pid)) {//只能是pid
                                    if (!is_int($pf_pid)) $pf_pid = intval($pf_pid);
                                    if ($pf_pid < 1) break;
                                    $have_postflag = false;//是否在postflag表中存在记录
                                    $isfirst = GetIsFirstPostSet($ispostfirst,$pf_pid);
                                    $old_isfirst = 0;//旧的postflag是否为作为FirstPost处理
                                    //获取原有的PostFlag数据(不论是否hide):
                                    if (!isset($postflag_olds[$pf_pid])) {
                                        if (isset($postflag_old)) unset($postflag_old);
                                        $postflag_old = db_find_one($PostFlagTable, array('pid' => $pf_pid));//不管isfirst
                                        if (!empty($postflag_old)) {
                                            $postflag_olds[$pf_pid] = &$postflag_old;
                                        }
                                    }
                                    if (isset($postflag_olds[$pf_pid])) {
                                        if (empty($postflag_old)) $postflag_old = &$postflag_olds[$pf_pid];
                                        $have_postflag = true;
                                    } else $postflag_old = null;
                                    if($have_postflag){
                                        $old_isfirst = (int)$postflag_old['isfirst'];
                                    }

                                    $opt_Flags = &$useflags;
                                    $opt_Flag_list = array_keys($opt_Flags);
                                    $opt_Flag_list_dels = 0;
                                    foreach ($opt_Flag_list as &$opt_Flag_p) {
                                        if (!isset($ManagePostFlagCfg1[$opt_Flag_p])) {//过滤无效标记:
                                            unset($opt_Flags[$opt_Flag_p]);
                                            $opt_Flag_list_dels++;
                                        }
                                    }
                                    if ($opt_Flag_list_dels > 0) {
                                        $opt_Flag_list = array_keys($opt_Flags);
                                    }
                                    $opt_Flag_list_dels = 0;
                                    //与原来的postflag记录相对比:
                                    if ($have_postflag) {
                                        foreach ($opt_Flag_list as &$flag) {
                                            $tagReason = &$opt_Flags[$flag];
                                            $_opt_Gidx = $PostFlagNodesCfg[$flag]['Group'];
                                            //同组相排斥
                                            $cur_opt_mps = &$ManagePostFlagCfg[$_opt_Gidx];
                                            if($old_isfirst != $isfirst) $cur_opt_mps = &$PostFlagNodesCfg;//isfirst不同则清除
                                            foreach ($cur_opt_mps as $ogK => &$ogV) {
                                                if ($postflag_old[$ogK . '_g'] > 0) {
                                                    //可以对隐藏的postflag记录进行无条件修改
                                                    if ($_curGid < 1 || $postflag_old['hide'] == 1 || ($postflag_old[$ogK . '_g'] > $_curGid) || ($postflag_old[$ogK . '_g'] == $_curGid && $postflag_old[$ogK . '_u'] != $_curUid)) {
                                                        //如果在标记后,标记者被降权,则无法修改自己之前的标记,以组织优先,权限相同者,不能修改同级标记
                                                        unset($opt_Flags[$flag]);
                                                        $opt_Flag_list_dels++;
                                                        break;
                                                    }
                                                    if ($flag == $ogK && empty($tagReason) && $old_isfirst == $isfirst) {
                                                        unset($opt_Flags[$flag]);
                                                        $opt_Flag_list_dels++;
                                                        break;
                                                    }
                                                    //将同级的其它加入清除队列:
                                                    if ($flag != $ogK) {
                                                        if(!isset($clearFlagSql[$pf_pid]))
                                                            $clearFlagSql[$pf_pid] = array('upd' => array(), 'chgord' => 0);
                                                        $clearFlagSql[$pf_pid]['upd'][$ogK] = '';
                                                        $clearFlagSql[$pf_pid]['upd'][$ogK . '_g'] = 0;
                                                        $clearFlagSql[$pf_pid]['upd'][$ogK . '_u'] = 0;
                                                        if ($PostFlagNodesCfg[$ogK]['order'] != 0) {
                                                            $clearFlagSql[$pf_pid]['chgord'] += (int)$PostFlagNodesCfg[$ogK]['order'];
                                                        }
                                                    } else {
                                                        $clearFlagSql[$pf_pid]['upd'][$ogK] = '';
                                                        //先减去,后面再加
                                                        if ($PostFlagNodesCfg[$ogK]['order'] != 0) {
                                                            if (!isset($clearFlagSql[$pf_pid]['chgord'])) $clearFlagSql[$pf_pid]['chgord'] = 0;
                                                            $clearFlagSql[$pf_pid]['chgord'] += (int)$PostFlagNodesCfg[$ogK]['order'];
                                                        }
                                                    }
                                                }
                                            }
                                            unset($cur_opt_mps);
                                        }
                                        unset($flag, $tagReason);
                                    }
                                    if ($opt_Flag_list_dels > 0) {
                                        $opt_Flag_list = array_keys($opt_Flags);
                                    }
                                    $opt_Flag_list_dels = 0;
                                    //帖子与标记权限验证:
                                    if (!ValidManagePostFlagForPostAuth($pf_pid, $opt_Flags, $_curUid, $_curGid, $EnablePFlags, $EnablePFlagsSelf)) {
                                        break;//没要需要的权限,或者部分被限制
                                    }
                                    $FirstPostUniqueItem = null;
                                    if($isfirst){
                                        $FirstPostUniqueItem = $PostFlagCfg['FirstPostUniqueItem'];
                                        if(empty($FirstPostUniqueItem)) $FirstPostUniqueItem = 'fid';
                                    }
                                    //对即将添加的标记初步处理和严格的权限验证:
                                    foreach ($opt_Flag_list as &$flag) {
                                        $tagReason = &$opt_Flags[$flag];
                                        $CurFlagCfg = &$PostFlagNodesCfg[$flag];
                                        if (!empty($CurFlagCfg['SubjectFmt']))
                                            $SubjectFmt = $CurFlagCfg['SubjectFmt'];
                                        //可能有漏网之鱼JSON:
                                        if (strlen($tagReason) > 7 && $tagReason{0} == '{' && $tagReason{strlen($tagReason) - 1} == '}') {
                                            $_tagReason = xn_json_decode($tagReason);
                                            if (isset($_tagReason['reason'])) {
                                                $tagReason = &$_tagReason['reason'];
                                            }
                                            unset($_tagReason);
                                        }
                                        if(isset($cur_post_parents)) unset($cur_post_parents);
                                        //一篇主题只允许存在一个此类标记:
                                        if ($CurFlagCfg['Unique']) {//具有唯一性,需要检查:
                                            //检查Unique标记所需要的权限:
                                            $Unique_Valid = false;
                                            //第一步:获取此pid的父级:
                                            $cur_post_parents = &GetInfoCatalogWithOwn(TX_INFO_TYPE_POST, $pf_pid);
                                            if (!empty($cur_post_parents)) {
                                                //第二步:获取所有回复的pid:
                                                $pf_tid = $cur_post_parents['tid'];
                                                $pids = array();
                                                if(!$isfirst) {//非主帖:
                                                    $postRS = db_find('post', array('tid' => $pf_tid,'isfirst'=>$isfirst), array(), 1, 9999, '', array('pid'));
                                                    if (!empty($postRS)) {
                                                        foreach ($postRS as $pidV) {
                                                            $pids[] = intval($pidV['pid']);
                                                        }
                                                    }
                                                }
                                                else{
                                                    $pk_firsts = &PickupFirstPosts($pf_pid,$FirstPostUniqueItem);
                                                    $pids = array_keys($pk_firsts);
                                                }
                                               if(!empty($pids)){
                                                   //登记:
                                                   if (!isset($UniqueFlags[$pf_tid])) $UniqueFlags[$pf_tid] = array();
                                                   if (isset($UniqueFlags[$pf_tid][$flag])) {
                                                       $uniq_pid = key($UniqueFlags[$pf_tid][$flag]);
                                                       $uniq_reason = current($UniqueFlags[$pf_tid][$flag]);
                                                       if (!empty($tagReason) || empty($uniq_reason) || $isfirst != $old_isfirst) {
                                                           //删除之前的,保留最后一个:
                                                           if (isset($updates[$uniq_pid][$flag])) {
                                                               unset($updates[$uniq_pid][$flag], $updates[$uniq_pid][$flag . '_u'], $updates[$uniq_pid][$flag . '_g']);
                                                               if (empty($updates[$uniq_pid]))
                                                                   unset($updates[$uniq_pid]);
                                                           }
                                                           if ($CurFlagCfg['order'] != 0) {
                                                               if (!isset($orderqueues[$uniq_pid]))
                                                                   $orderqueues[$uniq_pid] -= (int)$CurFlagCfg['order'];//撤消积分
                                                           }
                                                           if (isset($clearUnique[$uniq_pid][$flag])) {
                                                               unset($clearUnique[$uniq_pid][$flag]);
                                                               if (empty($clearUnique[$uniq_pid]))
                                                                   unset($clearUnique[$uniq_pid]);
                                                           }
                                                           $UniqueFlags[$pf_tid][$flag] = array($pf_pid => $tagReason);//替换
                                                       }
                                                   } else {
                                                       $UniqueFlags[$pf_tid][$flag] = array($pf_pid => $tagReason);//新加
                                                   }
                                                   //第三步:获取所有hide=0的postflag相关的记录:
                                                   $postflagRS = db_find($PostFlagTable, array('hide' => 0,'isfirst'=>$isfirst, 'pid' => $pids, $flag . '_u' => array('<>' => 0)), array(), 1, count($pids), 'pid', array('pid','tid', $flag, $flag . '_u', $flag . '_g'));
                                                   if (!empty($postflagRS)) {
                                                       $strip_pids = $strip_tids =array();
                                                       foreach ($postflagRS as $_pid => &$_PFV) {
                                                           if ($_PFV[$flag . '_g'] == 0 || $_PFV[$flag . '_g'] > $_curGid || ($_PFV[$flag . '_g'] == $_curGid && $_PFV[$flag . '_u'] == $_curUid)) {
                                                               if ($pid != $_pid) //防止后续覆盖
                                                               {
                                                                   $strip_pids[] = $_pid;
                                                                   $strip_tids[] =intval($_PFV['tid']);
                                                               } else {
                                                                   $Unique_Valid = true;//自己修改标记内容
                                                               }
                                                           } else //没有覆盖权限
                                                           {
                                                               $strip_pids = $strip_tids = null;
                                                               break;
                                                           }
                                                       }
                                                       if (!empty($strip_pids) || !empty($strip_tids)) {
                                                           if (!isset($clearUnique[$_pid])) $clearUnique[$_pid] = array();
                                                           if (!isset($clearUnique[$_pid][$flag])) $clearUnique[$_pid][$flag] = array();
                                                           $clearUnique[$_pid][$flag]['upd'] = array('cond' => array('pid' => $strip_pids), 'update' => array($flag . '_u' => 0, $flag . '_g' => 0, $flag => ''));;
                                                           if ($CurFlagCfg['order'] != 0){
                                                               $Uniq_first_postflag = 0;
                                                               if(isset($postflag_olds[$_pid])){
                                                                   $Uniq_first_postflag = intval($postflag_olds[$_pid]['isfirst']);
                                                               }
                                                               else{//新增的需要考虑IsFirstPost:
                                                                   $Uniq_first_postflag = GetIsFirstPostSet($ispostfirst,$_pid);
                                                               }
                                                               $chgord_sql = 'UPDATE `' . $db->tablepre . 'post` SET `prank`=`prank`-(' . $CurFlagCfg['order'] . ') WHERE pid IN (' . implode(',', $strip_pids) . ')';
                                                               if($Uniq_first_postflag){//$pf_tid
                                                                   $chgord_sql = 'UPDATE `' . $db->tablepre . 'thread` SET `trank`=`trank`-(' . $CurFlagCfg['order'] . ') WHERE tid IN (' . implode(',', $strip_tids) . ')';
                                                               }
                                                               $clearUnique[$_pid][$flag]['execsql'] = $chgord_sql;
                                                           }
                                                           $Unique_Valid = true;
                                                       }
                                                   } else {
                                                       //无须登记$clearUnique语句
                                                       $Unique_Valid = true;//不存在postflag记录,要新增
                                                   }
                                                   unset($postflagRS);
                                               }
                                               else
                                                   $Unique_Valid = true;//不存在postflag记录,要新增
                                            }
                                            if (!$Unique_Valid) {//缺乏权限,不能设置Unique标记,跳到下一个
                                                unset($opt_Flags[$flag]);
                                                continue;
                                            }
                                        }

                                        if (!isset($updates[$pf_pid])) $updates[$pf_pid] = array('pid' => $pf_pid);
                                        $updates[$pf_pid][$flag] = &FillPostFlagText($SubjectFmt, $CurFlagCfg, array('flagname' => $flag, 'reason' => $tagReason));
                                        $updates[$pf_pid][$flag . '_u'] = $_curUid;
                                        $updates[$pf_pid][$flag . '_g'] = $_curGid;
                                        //目录数据:
                                        if($old_isfirst != $isfirst) $updates[$pf_pid]['isfirst'] = $isfirst;
                                        if(!isset($cur_post_parents)) $cur_post_parents = &GetInfoCatalogWithOwn(TX_INFO_TYPE_POST, $pf_pid);
                                        if(!empty($cur_post_parents)){
                                            $updates[$pf_pid]['tid'] = $cur_post_parents['tid'];
                                            $updates[$pf_pid]['fid'] = $cur_post_parents['fid'];
                                        }
                                        if ($CurFlagCfg['order'] != 0) {
                                            if (!isset($orderqueues[$pf_pid]))
                                                $orderqueues[$pf_pid] = 0;
                                            $orderqueues[$pf_pid] += (int)$CurFlagCfg['order'];
                                        }
                                        unset($CurFlagCfg);
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                    unset($optStdCmds[$curCmd]);
                }

                $opt_pid_list = array_keys($clearFlagSql);
                //执行清除:
                if (!empty($clearFlagSql)) {
                    foreach ($opt_pid_list as $_pid) {
                        //$clearFlagSql 的二级上$_runSqlparam有两个组成部分：upd,chgord
                        $_runSqlparam = &$clearFlagSql[$_pid];
                        $optret = db_update($PostFlagTable, array('pid' => $_pid), $_runSqlparam['upd']);
                        if ($optret !== false) {
                            $succopt++;
                            if ($_runSqlparam['chgord'] != 0) {//有两种操作,分别
                                $del_first_postflag = 0;
                                if(isset($postflag_olds[$_pid])){
                                    $del_first_postflag = intval($postflag_olds[$_pid]['isfirst']);
                                }
                                else{//新增的需要考虑IsFirstPost:
                                    $del_first_postflag = GetIsFirstPostSet($ispostfirst,$_pid);
                                }
                                if($del_first_postflag){
                                    $del_post_parents = &GetInfoCatalogWithOwn(TX_INFO_TYPE_POST, $_pid);
                                    $_tid = $del_post_parents['tid'];
                                    $chgord_sql = "UPDATE `{$db->tablepre}thread` SET `trank`=`trank`-({$_runSqlparam['chgord']}) WHERE `tid`={$_tid}";
                                }
                                else
                                    $chgord_sql = "UPDATE `{$db->tablepre}post` SET `prank`=`prank`-({$_runSqlparam['chgord']}) WHERE `pid`={$_pid}";
                                db_exec($chgord_sql);
                            }
                        } else
                            unset($clearFlagSql[$_pid]);
                    }
                    //记录删除成功的标记:
                    foreach ($clearFlagSql as $_pid => &$succflagRec) {
                        foreach ($succflagRec['upd'] as $succflag => &$optsql) {
                            if (isset($PostFlagNodesCfg[$succflag])) {
                                if (!isset($delflags[$_pid])) $delflags[$_pid] = array();
                                if (empty($optsql) && isset($postflag_olds[$_pid])) {
                                    $optsql = &$postflag_olds[$_pid][$succflag];
                                }
                                $delflags[$_pid][$succflag] = $optsql;
                            }
                        }
                    }
                    unset($clearFlagSql);//清除
                }
                //执行增加标记:
                if (!empty($updates)) {
                    $opt_pid_list = array_keys($updates);
                    foreach ($opt_pid_list as $_pid) {
                        $have_postflag = isset($postflag_olds[$_pid]);
                        $isfirst = GetIsFirstPostSet($ispostfirst,$_pid);
                        $old_isfirst = 0;
                        if($have_postflag) $old_isfirst = (int)$postflag_olds[$_pid]['isfirst'];
                        $update_item = &$updates[$_pid];
                        $optret = false;
                        $p_tid = $p_fid = $p_pid = 0;
                        if ($have_postflag) {
                            $update_cond = array('pid' => &$update_item['pid']);
                            $p_pid = $update_item['pid'];
                            $p_tid = $update_item['tid'];
                            $p_fid = $update_item['fid'];
                            $p_isfirst = null;
                            if(isset($update_item['isfirst']) && $old_isfirst == $isfirst) {
                                $p_isfirst = $update_item['isfirst'];
                                unset($update_item['isfirst']);
                            }
                            unset($update_item['pid'],$update_item['tid'],$update_item['fid']);
                            $optret = db_update($PostFlagTable, $update_cond, $update_item);
                            if ($optret < 1){//可能在这执行中途被删除了,需要重新添加
                                $update_item['pid'] = $p_pid;
                                $update_item['tid'] = $p_tid;
                                $update_item['fid'] = $p_fid;
                                if($p_isfirst !== null) $update_item['isfirst'] = $p_isfirst;
                            }
                        }
                        if ($optret < 1)
                            $optret = db_insert($PostFlagTable, $update_item);
                        if ($optret > 0) {//受影响的行数或者新增的ID号
                            $succopt++;
                            $sum_rank = $orderqueues[$_pid];
                            if ($sum_rank != 0) {
                                $is_first_postflag = GetIsFirstPostSet($ispostfirst,$_pid);
                                if(!$is_first_postflag)
                                    $_sql1 = "UPDATE `{$db->tablepre}post` SET `prank`=`prank`+({$sum_rank}) WHERE `pid`={$_pid}";
                                else{
                                    $add_post_parents = &GetInfoCatalogWithOwn(TX_INFO_TYPE_POST, $_pid);
                                    $_tid = $add_post_parents['tid'];
                                    $_sql1 = "UPDATE `{$db->tablepre}thread` SET `trank`=`trank`+({$sum_rank}) WHERE `tid`={$_tid}";
                                }
                                db_exec($_sql1);
                            }
                            //如果增加flag不成功,那么clearUnique操作就没有意义:
                            //结构:array({pid}=>array({flag}=>array('upd'=>array('cond'=>array(),'update'=>array()),'execsql'=>{sql}))...)
                            if (isset($clearUnique[$_pid]) && !empty($clearUnique[$_pid])) {
                                foreach ($clearUnique[$_pid] as $pf_flag => &$execsqls) {
                                    $_sql2 = null;
                                    if (isset($execsqls['execsql'])) $_sql2 = &$execsqls['execsql'];
                                    $_unq_upd = &$execsqls['upd'];
                                    if (!empty($_unq_upd)) $optr = db_update($PostFlagTable, $_unq_upd['cond'], $_unq_upd['update']);
                                    if (!empty($_sql2)) $optr = db_exec($_sql2);
                                    unset($_sql2);
                                }
                                unset($_unq_upd, $execsqls);
                            }
                            if (!isset($addflags[$_pid])) $addflags[$_pid] = array();
                            //flag=>reason
                            foreach ($update_item as $succflag => &$optX) {
                                if (!empty($PostFlagNodesCfg[$succflag])) {
                                    $addflags[$_pid][$succflag] = &$optX;
                                }
                            }
                            unset($optX);
                        }
                        unset($update_item);
                    }
                }
            }
        }
    }

}

//处理返回结果:
$retMsg = '';
$optret = 0;
if ($succopt <= 0) {
    $optret = -1;
    $retMsg = '没有操作被成功执行!';
}
$arr = array('code' => $optret, 'pid' => $pid);
if (!empty($delflags) || !empty($addflags) || !empty($otheropt) || !empty($getinfo_ret) || !empty($message_fmt_chg)) {
    $arr['sucopt'] = array('del' => &$delflags, 'add' => &$addflags);
    $updflags = array();
    if (!empty($delflags) && !empty($addflags)){//flag修改的登记补丁:
        foreach($delflags  as $pid1 => &$vflags){
            if(isset($addflags[$pid1])){
                foreach($vflags as $vfk => &$vfv){
                    if(isset($addflags[$pid1][$vfk])){
                        if(!isset($updflags[$pid1])) $updflags[$pid1] = array();
                        $updflags[$pid1][$vfk] = &$addflags[$pid1][$vfk];
                    }
                }
            }
        }
        if(!empty($updflags)){
            foreach($updflags  as $pid1 => &$vflags){
                foreach($vflags as $vfk => &$vfv){
                    unset($delflags[$pid1][$vfk],$addflags[$pid1][$vfk]);
                    if(empty($delflags[$pid1])) unset($delflags[$pid1]);
                    if(empty($addflags[$pid1])) unset($addflags[$pid1]);
                }
            }
            $arr['sucopt']['upd'] = &$updflags;
        }
    }
    if (!empty($otheropt)) $arr['sucopt']['other'] =  &$otheropt;
    if (!empty($message_fmt_chg)) $arr['sucopt']['message_fmt'] =  &$message_fmt_chg;//针对striphtml操作返回的结果
    if (!empty($getinfo_ret)) $arr['sucopt']['getinfo'] =  &$getinfo_ret;
    if (empty($arr['sucopt']['del'])) unset($arr['sucopt']['del']);
    if (empty($arr['sucopt']['add'])) unset($arr['sucopt']['add']);
    if (!$ajax && !empty($PostFlagNodesCfg)) {
        if (!empty($addflags)) {
            foreach ($addflags as $pid1 => &$vflags) {
                $retMsg .= "在回帖[{$pid1}]上添加了标记[";
                $fglist = '';
                foreach ($vflags as $vflag => &$vfinfo) {
                    $fglist .= ',' . $PostFlagNodesCfg[$vflag]['title'];
                }
                if (!empty($fglist)) $fglist = substr($fglist, 1);
                $retMsg .= $fglist . '];'.PHP_EOL;
            }
        }
        else{
            if(isset($arr['sucopt']['add'])) unset($arr['sucopt']['add']);
        }
        if (!empty($delflags)) {
            foreach ($delflags as $pid1 => &$vflags) {
                $retMsg .= "在回帖[{$pid1}]上删除了标记[";
                $fglist = '';
                foreach ($vflags as $vflag => &$vfinfo) {
                    $fglist .= ',' . $PostFlagNodesCfg[$vflag]['title'];
                }
                if (!empty($fglist)) $fglist = substr($fglist, 1);
                $retMsg .= $fglist . '];'.PHP_EOL;
            }
        }
        else{
            if(isset($arr['sucopt']['del'])) unset($arr['sucopt']['del']);
        }
        if (!empty($updflags)) {
            foreach ($updflags as $pid1 => &$vflags) {
                $retMsg .= "在回帖[{$pid1}]上修改了标记[";
                $fglist = '';
                foreach ($vflags as $vflag => &$vfinfo) {
                    $fglist .= ',' . $PostFlagNodesCfg[$vflag]['title'];
                }
                if (!empty($fglist)) $fglist = substr($fglist, 1);
                $retMsg .= $fglist . '];'.PHP_EOL;
            }
        }
        else{
            if(isset($arr['sucopt']['upd'])) unset($arr['sucopt']['upd']);
        }
        if (!empty($otheropt)) {
            foreach ($otheropt as $pid1 => &$vmsgs) {
                $retMsg .= "在回帖[{$pid1}]上进行了[";
                $fgmsg = '';
                foreach ($vmsgs as &$vmsg) {
                    $fgmsg .= ';' . $vmsg;
                }
                if (!empty($fgmsg)) $fgmsg = substr($fgmsg, 1);
                $retMsg .= $fgmsg . '];'.PHP_EOL;
            }
        }
    }
}
message($arr['code'], $retMsg, $arr);